package minformer;
import javax.microedition.io.file.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import java.io.*;
import java.util.Enumeration;
import java.util.Vector;


class FileBrowser implements CommandListener, Runnable
{
	private CommandListener externalListener;
	private List list;
	final static String ROOT_DIRECTORY = "/";
	final static String PARENT_DIRECTORY = "../";
	private final static int MODE_SCAN_DIRECTORY = 1;
	private final static int MODE_SHOW_RESULTS   = 2;
	private int currentMode;
	private String currentDir;
	private String selectedItem;
	private Vector items;
	private boolean onlyDirs;
	public final static Command cmdSelect = new Command("Выбрать", Command.SCREEN, 1);
	public final static Command cmdCancel = new Command("Отмена", Command.CANCEL, 2);
	private Display display;
	
	private FileConnection fileConnection;
	
	public FileBrowser()
	{
		items = new Vector();
		list = new List(null, List.IMPLICIT);
		list.addCommand(cmdSelect);
		list.addCommand(cmdCancel);
	}
	
	public void browse(String root, CommandListener externalListener, boolean onlyDirs, Display display)
	{
		this.display = display;
		this.externalListener = externalListener;
		this.onlyDirs = onlyDirs;
		
		if (root == null) root = ROOT_DIRECTORY;
		
		display.setCurrent(list);
		list.setCommandListener(this);
		showFolder(root);
	}
	

	private void showFolder(String path)
	{
		if (currentMode == MODE_SCAN_DIRECTORY) return;
		currentMode = MODE_SCAN_DIRECTORY;
		currentDir = path;
		new Thread(this).start();
	}
	
	private void enumRootsStd(Vector result)
	{
		Enumeration roots = FileSystemRegistry.listRoots();
		while (roots.hasMoreElements()) result.addElement(roots.nextElement());
	}
	
	private void enumFilesStd(Vector result, String fileName) throws IOException
	{
		FileConnection fileconn = (FileConnection) Connector.open("file://localhost"+fileName, Connector.READ);

		Enumeration list = fileconn.list();
		fileconn.close();
		
		result.addElement(PARENT_DIRECTORY);
		while (list.hasMoreElements())
		{
			String filename = (String) list.nextElement();
			result.addElement(filename);
		}
	}
	
	public void run() 
	{
		switch (currentMode)
		{
		case MODE_SCAN_DIRECTORY:
			try
			{
				items.removeAllElements();
				if (currentDir.equals(ROOT_DIRECTORY))
				{
					enumRootsStd(items);
				}
				else
				{
					enumFilesStd(items, currentDir);
				}
			} 
			catch (Exception e)
			{
				e.printStackTrace();
			}
			
			currentMode = MODE_SHOW_RESULTS;
			display.callSerially(this);
			break;
			
		case MODE_SHOW_RESULTS:
			
			// Show last path element at caption 
			int index1 = -1, index2 = -1;
			boolean isDelim;
			for (int i = currentDir.length()-1; i >= 0; i--)
			{
				isDelim = (currentDir.charAt(i) == '/');
				if (isDelim)
				{
					if (index1 == -1) index1 = i;
					else if (index2 == -1) index2 = i;
					else break;
				}
			}
			
			list.setTitle
			(
				(index1 != -1) && (index2 != -1) ? 
				currentDir.substring(index2+1, index1) : 
				"Root"
			);

			// Show directory content
			list.deleteAll();
			
			// Show dirs
			String itemText;
			for (int i = 0; i < items.size(); i++)
			{
				itemText = (String)items.elementAt(i);
				if (!itemText.endsWith("/")) continue;
				list.append(itemText, null);
			}
			
			// Show files
			if (!onlyDirs) for (int i = 0; i < items.size(); i++)
			{
				itemText = (String)items.elementAt(i);
				if (itemText.endsWith("/")) continue;
				list.append(itemText, null);
			}
			itemText = null;
			break;
		}
	}
	
	public void commandAction(Command c, Displayable d)
	{
		if ((c == cmdSelect) || (c == List.SELECT_COMMAND))
		{
			int index = list.getSelectedIndex();
			if (index < 0) return;
			String itemText = list.getString(index);
			String parentDir = null;
			selectedItem = currentDir+itemText;
			if (itemText == PARENT_DIRECTORY)
			{
				parentDir = null;
				for (int i = currentDir.length()-2; i >= 0; i--) if (currentDir.charAt(i) == '/')
				{
					parentDir = currentDir.substring(0, i+1);
					break;
				}
				if (parentDir != null) showFolder(parentDir);
			}
			else if (itemText.endsWith("/"))
			{
				showFolder(selectedItem);
			}
			else
			{
				if (externalListener != null) externalListener.commandAction(cmdSelect, d);
			}
		}
		else if (c == cmdCancel) externalListener.commandAction(c, d);
	}
	
	public String getValue()
	{
		return selectedItem;
	}
	
	public void openFile(String fileName) throws IOException
	{
		close();
		fileConnection = (FileConnection) Connector.open("file://" + fileName,Connector.READ);		
	}
	
	public InputStream openInputStream() throws IOException
	{
		return fileConnection.openInputStream();
	}
	
	public OutputStream openOutputStream() throws IOException
	{
		OutputStream result;
		if ( !fileConnection.exists() ) fileConnection.create();
		result = fileConnection.openOutputStream();
		return result;
	}
	
	public void close() throws IOException
	{
		if (fileConnection != null)
		{
			fileConnection.close();
			fileConnection = null;
		}
	}
	
	public long fileSize() throws IOException
	{
		long result = (fileConnection == null) ? -1 : fileConnection.fileSize();
		return result;
	}
}
